﻿using System.Net.Http.Headers;

namespace wwm.LeetCodeHelper.Servers;

public class HttpRequestHelper
{
    // Http 传不同的参数方式实现HttpContent
    /*
    目前官方实现有四种
    MultipartFormDataContent、FormUrlEncodedContent、StringContent、StreamContent
    和上面的总结进行一个对比就能发现:
    MultipartFormDataContent=》multipart/form-data
    FormUrlEncodedContent =》application/x-www-form-urlencoded
    StringContent =》application/json等
    StreamContent =》binary
    */
    private static HttpClient _httpClient;
    public static void SetHttpClient(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    /// <summary>
    /// 统一request请求方法
    /// </summary>
    /// <param name="options"></param>
    /// <param name="headers"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public static async Task<HttpResponseMessage> Request(HttpRequestOptions options, Dictionary<string, string> headers = null)
    {
        //HttpClient client = null;
        if (_httpClient == null)
        {
            _httpClient = new HttpClient();
        }
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        if (options.method.Equals("get", StringComparison.CurrentCultureIgnoreCase))
        {
            if (headers != null)
            {
                //client.DefaultRequestHeaders.Clear();
                foreach (var item in headers)
                {
                    _httpClient.DefaultRequestHeaders.Add(item.Key, item.Value);
                }
                //client.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            }
            return await _httpClient.GetAsync(options.url);
        }
        else if (options.method.Equals("post", StringComparison.CurrentCultureIgnoreCase))
        {
            if (options.form == null)
            {
                //使用json请求
                var body = options.body.GetType().Name switch
                {
                    "string" => (string)options.body,
                    "object" => JsonSerializer.Serialize(options.body),
                    _ => options.body.ToString(),
                };
                return await PostAsync(options.url, body, headers);

            }
            else if (options.body == null)
            {
                //使用form请求
                var form = options.form;
                return await PostAsync(options.url, form, headers);
            }
            else
            {
                throw new Exception("暂未实现此方法");
            }
        }
        else
        {
            throw new Exception("暂未实现此方法");
        }
    }
    public static async Task<HttpResponseMessage> PostAsync(string url, string body, Dictionary<string, string> headers)
    {
        HttpClient client = null;
        if (_httpClient == null)
        {
            client = new HttpClient();
        }
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        using var stringContent = new StringContent(body);
        stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        if (headers != null)
        {
            foreach (var item in headers)
            {
                stringContent.Headers.Add(item.Key, item.Value);
            }
        }
        HttpResponseMessage response = await client.PostAsync(url, stringContent);
        return response;
    }

    public static async Task<HttpResponseMessage> PostAsync(string url, Dictionary<string, string> form, Dictionary<string, string> headers)
    {
        HttpClient client = null;
        if (_httpClient == null)
        {
            client = new HttpClient();
        }
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        using var multipartFormDataContent = new MultipartFormDataContent();
        foreach (var item in form)
        {
            multipartFormDataContent.Add(new StringContent(item.Value), String.Format("\"{0}\"", item.Value));
        }
        multipartFormDataContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        if (headers != null)
        {
            foreach (var item in headers)
            {
                multipartFormDataContent.Headers.Add(item.Key, item.Value);
            }
        }
        HttpResponseMessage response = await client.PostAsync(url, multipartFormDataContent);
        return response;
    }
    /// <summary>
    /// Post From Data
    /// </summary>
    /// <param name="url"></param>
    /// <param name="form"></param>
    /// <returns></returns>
    public static async Task<string> PostAsyncForm(string url, Dictionary<string, string> form)
    {
        HttpClient client = null;
        if (_httpClient == null)
        {
            client = new HttpClient();
        }
        using var multipartFormDataContent = new MultipartFormDataContent();
        foreach (var item in form)
        {
            multipartFormDataContent.Add(new StringContent(item.Value), String.Format("\"{0}\"", item.Value));
        }
        HttpResponseMessage response = await client.PostAsync(url, multipartFormDataContent);
        response.EnsureSuccessStatusCode();
        string responseBody = await response.Content.ReadAsStringAsync();
        return responseBody;
    }

    /// <summary>
    /// 使用post方法异步请求
    /// </summary>
    /// <param name="url">目标链接</param>
    /// <param name="json">发送的参数字符串，只能用json</param>
    /// <returns>返回的字符串</returns>
    public static async Task<string> PostAsyncJson(string url, string json)
    {

        //HttpClient client = new HttpClient();
        HttpClient client = null;
        if (_httpClient == null)
        {
            client = new HttpClient();
        }
        HttpContent content = new StringContent(json);
        content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
        HttpResponseMessage response = await client.PostAsync(url, content);
        response.EnsureSuccessStatusCode();
        string responseBody = await response.Content.ReadAsStringAsync();
        return responseBody;
    }

    /// <summary>
    /// 使用post方法异步请求
    /// </summary>
    /// <param name="url">目标链接</param>
    /// <param name="data">发送的参数字符串</param>
    /// <param name="header"></param>
    /// <param name="Gzip"></param>
    /// <returns>返回的字符串</returns>
    public static async Task<string> PostAsync(string url, string data, Dictionary<string, string> header = null, bool Gzip = false)
    {
        //HttpClient client = new HttpClient(new HttpClientHandler() { UseCookies = false });
        HttpClient client = null;
        if (_httpClient == null)
        {
            client = new HttpClient();
        }
        HttpContent content = new StringContent(data);
        if (header != null)
        {
            client.DefaultRequestHeaders.Clear();
            foreach (var item in header)
            {
                client.DefaultRequestHeaders.Add(item.Key, item.Value);
            }
        }
        HttpResponseMessage response = await client.PostAsync(url, content);
        response.EnsureSuccessStatusCode();
        string responseBody = "";
        if (Gzip)
        {
            var inputStream = await response.Content.ReadAsStreamAsync();
            responseBody = new StreamReader(inputStream).ReadToEnd();
        }
        else
        {
            responseBody = await response.Content.ReadAsStringAsync();

        }
        return responseBody;
    }

    /// <summary>
    /// 使用get方法异步请求
    /// </summary>
    /// <param name="url">目标链接</param>
    /// <param name="header"></param>
    /// <param name="Gzip"></param>
    /// <returns>返回的字符串</returns>
    public static async Task<string> GetAsync(string url, Dictionary<string, string> header = null, bool Gzip = false)
    {
        //HttpClient client = new HttpClient(new HttpClientHandler() { UseCookies = false });
        //HttpClient client = new HttpClient();
        HttpClient client = null;
        if (_httpClient == null)
        {
            client = new HttpClient();
        }
        if (header != null)
        {
            client.DefaultRequestHeaders.Clear();
            foreach (var item in header)
            {
                client.DefaultRequestHeaders.Add(item.Key, item.Value);
            }
        }
        HttpResponseMessage response = await client.GetAsync(url);
        response.EnsureSuccessStatusCode();//用来抛异常的
        string responseBody = "";
        if (Gzip)
        {
            var inputStream = await response.Content.ReadAsStreamAsync();
            responseBody = new StreamReader(inputStream).ReadToEnd();
        }
        else
        {
            responseBody = await response.Content.ReadAsStringAsync();

        }
        return responseBody;
    }

    /// <summary>
    /// 使用post返回异步请求直接返回对象
    /// </summary>
    /// <typeparam name="T">返回对象类型</typeparam>
    /// <typeparam name="T2">请求对象类型</typeparam>
    /// <param name="url">请求链接</param>
    /// <param name="obj">请求对象数据</param>
    /// <returns>请求返回的目标对象</returns>
    public static async Task<T> PostObjectAsync<T, T2>(string url, T2 obj)
    {
        string json = JsonSerializer.Serialize(obj);
        string responseBody = await PostAsyncJson(url, json);
        return JsonSerializer.Deserialize<T>(responseBody);
    }

    /// <summary>
    /// 使用Get返回异步请求直接返回对象
    /// </summary>
    /// <typeparam name="T">请求对象类型</typeparam>
    /// <param name="url">请求链接</param>
    /// <returns>返回请求的对象</returns>
    public static async Task<T> GetObjectAsync<T>(string url)
    {
        string responseBody = await GetAsync(url);
        return JsonSerializer.Deserialize<T>(responseBody);
    }
}